﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SuperKit {
    class CogUdpServer {
        public static bool IsActive => _instance != null && _instance.Started;

        public bool Started { get; set; } = false;
        private UdpClient udpcRecv;
        private string ip;
        private int port;

        private static CogUdpServer _instance = null;
        public static CogUdpServer Instance => _instance ?? (_instance = new CogUdpServer());

        public delegate void OnMessageProcessor(string ip, string msg);
        public OnMessageProcessor Processor { get; set; }
        private CancellationTokenSource canceller;

        public CogUdpServer(string ip, int port) {
            this.ip = ip;
            this.port = port;
        }

        private CogUdpServer() {
            this.ip = CogUdpClient.IpAddress;
            this.port = CogUdpClient.UDPServerPort;
        }

        public void Start() {
            try {
                if (!Started) { // 未监听的情况，开始监听
                    IPEndPoint localIpep = new IPEndPoint(IPAddress.Parse(ip), port); // 本机IP和监听端口号

                    udpcRecv = new UdpClient(localIpep);

                    canceller = new CancellationTokenSource();
                    Task.Factory.StartNew(OnReceiveMessage, canceller.Token);

                    Started = true;
                    //Messenger.Flush("UDP Server 成功启动：" + CogUdpClient.IpAddress);
                } else {
                    //Messenger.Flush("UDP Server 已经启动.");
                }
            } catch (SocketException) {
                //Messenger.Flush("UDP Server 端口已经被占用.");
            }
            
        }

        public void Close() {
            if (Started == false) {
                //Messenger.Flush("UDP Server 未启动.");
                return;
            }

            canceller.Cancel(); // 必须先关闭这个线程，否则会异常
            udpcRecv.Close();

            udpcRecv = null;
            Started = false;

            //Messenger.Flush("UDP Server 成功关闭.");
        }

        private void OnReceiveMessage() {
            IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Any, 0);
            while (true) {
                try {
                    byte[] bytRecv = udpcRecv.Receive(ref remoteIpep);
                    string message = Encoding.UTF8.GetString(bytRecv, 0, bytRecv.Length);


                    ProcessMessage(remoteIpep.Address.ToString(), message);
                }catch (SocketException ex) {
                    return;
                }catch (Exception ex) {
                    throw ex;
                    //Messager.addNotice(ex.Message);
                }
            }
        }

        private void ProcessMessage(string ip, string message) {
            if (Processor != null) {
                Processor.Invoke(ip, message);
            }
        }
    }
}
